package  
{
  import com.bit101.components.PushButton;
  import flash.display.Sprite;
  import flash.display.StageAlign;
  import flash.display.StageScaleMode;
  import flash.events.Event;
  import flash.media.Sound;
  import flash.media.SoundChannel;
	
	/**
   * ...
   * @author ivan
   */
  public class MusicTest extends Sprite 
  {
    
    private var channel:SoundChannel;
    
    public function MusicTest() 
    {
      stage.scaleMode = StageScaleMode.NO_SCALE;
      stage.align = StageAlign.TOP_LEFT;
      stage.stageFocusRect = false;
      
      new PushButton(this, 0, 0, "START", onStart);
      new PushButton(this, 0, 20, "STOP", onStop);
      new PushButton(this, 0, 40, "Lower Volume", onLowerVolume);
      new PushButton(this, 0, 60, "Normal Volume", onNormalVolume);
      new PushButton(this, 0, 80, "Fade Out", onFadeOut);
    }
    
    private var song:int;
    private function onStart(e:Event):void
    {
      if (channel)
        onFadeOut();
      
      var sound:Sound;
      switch (song++ % 2)
      {
        case 0: sound = new Music1(); break;
        case 1: sound = new Music2(); break;
      }
      
      channel = sound.play(0, int.MAX_VALUE);
    }
    
    private function onStop(e:Event = null):void
    {
      if (channel)
      {
        channel.stop();
        channel = null;
      }
    }
    
    private function onLowerVolume(e:Event):void
    {
      if (!channel) return;
      new Fade(channel, 0.2, 1000);
    }
    
    private function onNormalVolume(e:Event):void
    {
      if (!channel) return;
      new Fade(channel, 1, 1000);
    }
    
    
    private function onFadeOut(e:Event = null):void
    {
      new Fade(channel, 0, 1000, true);
      channel = null;
    }
    
  }

}

import flash.events.TimerEvent;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.utils.Timer;
import mge.Ease;
import mge.Timer;
import mge.Utils;

internal class Fade
{
  private const RESOLUTION:Number = 1 / 30;
  public function Fade(channel:SoundChannel, endVolume:Number, time:int, stopOnEnd:Boolean = false)
  {
    this.channel = channel;
    this.endVolume = endVolume;
    this.stopOnEnd = stopOnEnd;
    startVolume = channel.soundTransform.volume;
    
    fl_timer = new flash.utils.Timer(RESOLUTION);
    fl_timer.addEventListener(TimerEvent.TIMER, onTimer);
    fl_timer.start();
    mge_timer = new mge.Timer(time);
    mge_timer.start();
  }
  
  private function onTimer(e:TimerEvent):void
  {
    var delta:Number = mge_timer.getDelta(new Ease(Ease.cubicOut_01));
    var volume:Number = Utils.interpolate(startVolume, endVolume, delta);
    
    if (mge_timer.finished())
    {
      fl_timer.stop();
      fl_timer.removeEventListener(TimerEvent.TIMER, onTimer);
      volume = endVolume;
      if (stopOnEnd)
      {
        channel.stop();
        return;
      }
    }
    
    var st:SoundTransform = new SoundTransform(volume);
    channel.soundTransform = st;
  }
  
  private var channel:SoundChannel;
  private var stopOnEnd:Boolean;
  private var startVolume:Number;
  private var endVolume:Number;
  private var fl_timer:flash.utils.Timer;
  private var mge_timer:mge.Timer;
};